#pragma once

class CxThunk
{
public:
    CxThunk();

    void Attach(unsigned int pThis);
    void AttachMethod(unsigned int pMethod);

#pragma pack( push , 1)
    unsigned char   POP_EAX;
    unsigned char   PUSH;
    unsigned int    m_this;
    unsigned char   PUSH_EAX;
    unsigned char   JMP;
    unsigned int    m_method;
#pragma pack( pop )

};

class CxCallMethod
{
public:
    virtual ~CxCallMethod(){}

    virtual HRESULT CallMethod(unsigned int unThis, unsigned int unMethod, INT index, IxPairVec* pVec);

protected:
    CxThunk m_oThunk;
};

#define CALLMETHOD(type)                                                                                    \
class CxCallMethod##type : public CxCallMethod                                                               \
{                                                                                                           \
    virtual HRESULT CallMethod(unsigned int unThis, unsigned int unMethod, INT index, IxPairVec* pVec);     \
};

CALLMETHOD(INT)
CALLMETHOD(BOOL)
CALLMETHOD(BYTE)
CALLMETHOD(POINT)
CALLMETHOD(SIZE)
CALLMETHOD(RECT)
CALLMETHOD(COLORREF)
CALLMETHOD(BSTR)

class CxCallMethodIxDraw : public CxCallMethod
{
public:
    virtual HRESULT CallMethod(unsigned int unThis, unsigned int unMethod, INT index, IxPairVec* pVec);
};

class CxCallMethodAlignment : public CxCallMethod
{
public:
    virtual HRESULT CallMethod(unsigned int unThis, unsigned int unMethod, INT index, IxPairVec* pVec);
};